package com.zzh.tag.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by haodai on 17/8/18.
 */

public class TagView extends View {

    private static final String TAG = TagView.class.getSimpleName();

    private int width;
    private int height;

    private int x;//原始位置
    private int y;

    private int smallX = x;
    private int smallY = y;

    private int radius = 50;
    //小圆基数
    private int baseSmallRadius = 30;
    //小圆最小值  必须为2的幂数
    private int minSmallRadius = 4;
    //变化中的值
    private int smallRadius = baseSmallRadius;
    //小圆缩小 随着拉伸的长度缩小  比率暂时处理为 圆半径的6倍 后是不是改为随拉伸缩小率渐小
    private float smallerRatio = 6f;


    public TagView(Context context) {
        this(context, null);
    }

    public TagView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TagView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private Paint mPaint;
    private Paint mTextPaint;

    private void init() {
        this.mPaint = new Paint();
        this.mTextPaint = new Paint();
        this.mPaint.setColor(Color.RED);
        this.mPaint.setAntiAlias(true);
        this.mPaint.setDither(true);
        this.mPaint.setStrokeWidth(5);
        this.mPaint.setStyle(Paint.Style.FILL);
        this.mTextPaint.setColor(Color.WHITE);
        this.mTextPaint.setAntiAlias(true);
        this.mTextPaint.setTextSize(48);
        this.mPath = new Path();
    }

    //参数不能小于1  不做处理
    public void setText(String text) {
        if (TextUtils.isEmpty(text))
            return;
        if (text.length() >= 3)
            text = "99+";
        widthAndHeight = getWidthAndHeight(text, 48);
    }

    private boolean isDrawTriangle = true;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (isDrawTriangle) {
            drawTriangle(canvas);
            canvas.drawCircle(smallX, smallY, smallRadius, mPaint);
        }
        canvas.drawCircle(location[4], location[5], radius, mPaint);
        drawText(canvas);
    }

    private String textValue = "7";
    private int[] widthAndHeight;

    private void drawText(Canvas canvas) {
        if (widthAndHeight == null)
            widthAndHeight = getWidthAndHeight(textValue, 48);
        canvas.drawText(textValue, location[4] - widthAndHeight[0] / 2,
                location[5] + widthAndHeight[1] / 2, mTextPaint);
    }


    private void drawCircle(Canvas canvas) {
        canvas.drawCircle(smallX, smallY, smallRadius, mPaint);
        canvas.drawCircle(location[4], location[5], radius, mPaint);
    }

    private Path mPath;

    private void drawTriangle(Canvas canvas) {
        this.mPath.reset();

        this.mPath.moveTo(location[0], location[1]);

        this.mPath.lineTo(location[2], location[3]);

        this.mPath.cubicTo(location[14], location[15],
                location[16], location[17], location[8], location[9]);

        this.mPath.lineTo(location[6], location[7]);

        this.mPath.cubicTo(location[12], location[13],
                location[10], location[11], location[0], location[1]);

        canvas.drawPath(this.mPath, this.mPaint);
    }

    //------------------------小圆计算---------------------------------------

    /**
     * 0 对应小圆的一个x点
     * 1 对应小圆的一个y点  与0对应
     * 2 对应小圆的一个x点
     * 3 对应小圆的一个y点  与2对应
     * <p>
     * 4 大圆的中心点 x
     * 5 大圆的中心点 y
     * <p>
     * 6 对应大圆的一个x点
     * 7 对应大圆的一个y点  与6对应
     * 8 对应大圆的一个x点
     * 9 对应大圆的一个y点  与8对应
     * <p>
     * 10 对应小圆的操作点 x 对应0 1
     * 11 对应小圆的操作点 y 对应0 1
     * 12 对应大圆的操作点 x 对应6 7
     * 13 对应大圆的操作点 y 对应6 7
     * 14 对应小圆的操作点 x 对应2 3
     * 15 对应小圆的操作点 y 对应2 3
     * 16 对应大圆的操作点 x 对应8 9
     * 17 对应大圆的操作点 y 对应8 9
     * 以上所有操作点 均是1/3处理 就是大圆处是大圆的1／3  小圆处是小圆的1/3
     * <p>
     * 18 now  相系数
     */
    private float[] location;

    private float[] calculate(float x, float y, float[] nowValue) {
        double valueX = Math.abs(x - this.smallX);
        double valueY = Math.abs(y - this.smallY);
        double cosB = valueY / Math.sqrt(valueX * valueX
                + valueY * valueY);
        //最终值
        double endX = cosB/**cosB**/ * smallRadius;
        double endY = Math.sqrt(smallRadius * smallRadius - endX * endX);
        // 小圆处 x y 操作值
        double smallX = endX / 3 * 2;
        double smallY = endY / 3 * 2;
        int phaseSystem = getPhaseSystem(x, y);
        switch (phaseSystem) {
            case 1:
                nowValue[0] = this.smallX + (float) endX;
                nowValue[1] = this.smallY - (float) endY;
                nowValue[2] = this.smallX - (float) endX;
                nowValue[3] = this.smallY + (float) endY;

                nowValue[10] = this.smallX + (float) smallX;
                nowValue[11] = this.smallY - (float) smallY;
                nowValue[14] = this.smallX - (float) smallX;
                nowValue[15] = this.smallY + (float) smallY;
                break;
            case 2:
                nowValue[0] = this.smallX + (float) endX;
                nowValue[1] = this.smallY + (float) endY;
                nowValue[2] = this.smallX - (float) endX;
                nowValue[3] = this.smallY - (float) endY;

                nowValue[10] = this.smallX + (float) smallX;
                nowValue[11] = this.smallY + (float) smallY;
                nowValue[14] = this.smallX - (float) smallX;
                nowValue[15] = this.smallY - (float) smallY;
                break;
            case 3:
                nowValue[0] = this.smallX - (float) endX;
                nowValue[1] = this.smallY + (float) endY;
                nowValue[2] = this.smallX + (float) endX;
                nowValue[3] = this.smallY - (float) endY;

                nowValue[10] = this.smallX - (float) smallX;
                nowValue[11] = this.smallY + (float) smallY;
                nowValue[14] = this.smallX + (float) smallX;
                nowValue[15] = this.smallY - (float) smallY;
                break;
            case 4:
                nowValue[0] = this.smallX - (float) endX;
                nowValue[1] = this.smallY - (float) endY;
                nowValue[2] = this.smallX + (float) endX;
                nowValue[3] = this.smallY + (float) endY;

                nowValue[10] = this.smallX - (float) smallX;
                nowValue[11] = this.smallY - (float) smallY;
                nowValue[14] = this.smallX + (float) smallX;
                nowValue[15] = this.smallY + (float) smallY;
                break;
            default:
                break;
        }
        nowValue[4] = x;
        nowValue[5] = y;
        nowValue[18] = phaseSystem;
        nowValue = calculate(endX, endY, nowValue, phaseSystem);
        return nowValue;
    }

    //获取手势当前相系。 x ＝ 手势x ； y ＝ 手势 y  小圆使用
    private int getPhaseSystem(float x, float y) {
        //利用中心点的位置 处理相应的处理
        if (x < this.x && y < this.y) {
            //第一相系
            return 1;
        } else if (x > this.x && y < this.y) {
            //第二相系
            return 2;
        } else if (x > this.x && y > this.y) {
            //第三相系
            return 3;
        } else if (x < this.x && y > this.y) {
            //第四相系
            return 4;
        } else if (x == this.x && y < this.y) {
            //第一与第二交叉
            return 5;
        } else if (y == this.y && x > this.x) {
            //第二与第三交叉
            return 6;
        } else if (x == this.x && y > this.y) {
            //第三与第四交叉
            return 7;
        } else if (y == this.y && x < this.x) {
            //第四与第一交叉
            return 8;
        } else
            //不可能存在的
            return 9;
    }

    //----------------------大圆计算--------------------------------------------
    private float[] calculate(double valueX, double valueY,
                              float[] nowValue, int phaseSystem) {
        //最终值 只计算粗略  想要精细可以用三角函数计算
        double endX = valueX / smallRadius * radius;
        double endY = valueY / smallRadius * radius;

        //大圆处 x y 操作值
        double bigX = endX / 5;
        double bigY = endY / 5;

        switch (phaseSystem) {
            case 1:
                nowValue[6] = nowValue[4] + (float) endX;
                nowValue[7] = nowValue[5] - (float) endY;
                nowValue[8] = nowValue[4] - (float) endX;
                nowValue[9] = nowValue[5] + (float) endY;

                nowValue[12] = nowValue[4] + (float) bigX;
                nowValue[13] = nowValue[5] - (float) bigY;
                nowValue[16] = nowValue[4] - (float) bigX;
                nowValue[17] = nowValue[5] + (float) bigY;
                break;
            case 2:
                nowValue[6] = nowValue[4] + (float) endX;
                nowValue[7] = nowValue[5] + (float) endY;
                nowValue[8] = nowValue[4] - (float) endX;
                nowValue[9] = nowValue[5] - (float) endY;

                nowValue[12] = nowValue[4] + (float) bigX;
                nowValue[13] = nowValue[5] + (float) bigY;
                nowValue[16] = nowValue[4] - (float) bigX;
                nowValue[17] = nowValue[5] - (float) bigY;
                break;
            case 3:
                nowValue[6] = nowValue[4] - (float) endX;
                nowValue[7] = nowValue[5] + (float) endY;
                nowValue[8] = nowValue[4] + (float) endX;
                nowValue[9] = nowValue[5] - (float) endY;

                nowValue[12] = nowValue[4] - (float) bigX;
                nowValue[13] = nowValue[5] + (float) bigY;
                nowValue[16] = nowValue[4] + (float) bigX;
                nowValue[17] = nowValue[5] - (float) bigY;
                break;
            case 4:
                nowValue[6] = nowValue[4] - (float) endX;
                nowValue[7] = nowValue[5] - (float) endY;
                nowValue[8] = nowValue[4] + (float) endX;
                nowValue[9] = nowValue[5] + (float) endY;

                nowValue[12] = nowValue[4] - (float) bigX;
                nowValue[13] = nowValue[5] - (float) bigY;
                nowValue[16] = nowValue[4] + (float) bigX;
                nowValue[17] = nowValue[5] + (float) bigY;
                break;
            default:
                break;
        }
        return nowValue;
    }


    //开始的点击区间
    private int mClickSection = 50;
    //是否执行
    private boolean isExecution = false;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_UP:
                isExecution = false;
                //暂时处理
                Message message = handler.obtainMessage();
                if (isDrawTriangle)
                    message.what = PLACE;
                else message.what = CRUSHING;
                handler.sendMessage(message);
                break;
            case MotionEvent.ACTION_DOWN:
                if (Math.abs(event.getX() - x) < mClickSection &&
                        Math.abs(event.getY() - y) < mClickSection) {
                    isExecution = true;
                    Log.i(TAG, ">>>>>>>>true>>>>>>>>");
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (isExecution) {
                    //移动圆和中心之间的距离
                    double spacing = Math.sqrt(
                            Math.abs(event.getX() - this.smallX) * Math.abs(event.getX() - this.smallX)
                                    + Math.abs(event.getY() - this.smallY) * Math.abs(event.getY() - this.smallY)
                    );
                    //小圆缩小处理
                    smallRadius = (int) (baseSmallRadius * radius * smallerRatio / spacing);
                    if (smallRadius > baseSmallRadius) {
                        smallRadius = baseSmallRadius;
                        //跟随处理
                    }
                    if (smallRadius < minSmallRadius)
                        smallRadius = minSmallRadius;
                    location = calculate(event.getX(), event.getY(), location);


                    if (Math.abs(event.getX() - TagView.this.x) > radius * 8 ||
                            Math.abs(event.getY() - TagView.this.y) > radius * 8)
                        isDrawTriangle = false;
                    else {
                        if (!isDrawTriangle) {
                            if (Math.abs(event.getX() - TagView.this.x) <= radius ||
                                    Math.abs(event.getY() - TagView.this.y) <= radius) {
                                isDrawTriangle = true;
                            }
                        }
                    }
                    invalidate();
                } else Log.i(TAG, ">>>我在执行nimei>>>>>>>>>>>");
                break;
            default:
                break;
        }
        return true;
    }

    private static final int PLACE = 1;
    private static final int STOP = 2;
    private static final int FOLLOW = 3;
    private static final int CRUSHING = 4;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case PLACE:
                    place();
                    break;
                case FOLLOW:

                    break;
                case CRUSHING:
                    // TODO: 17/8/22 可以做完粉碎处理 在进行隐藏处理 此处要有隐藏回调
                    setVisibility(View.GONE);
                    break;
                case STOP:
                    TagView.this.location = new float[]{0f, 0f, 0f, 0f, TagView.this.x,
                            TagView.this.y, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f};
                    invalidate();
                    isDrawTriangle = true;
                    break;
                default:
                    break;
            }
        }
    };

    @Override
    public void setVisibility(int visibility) {
        if (visibility == View.GONE || visibility == View.INVISIBLE) {
            super.setVisibility(visibility);
            return;
        }
        Message message = handler.obtainMessage();
        message.what = STOP;
        handler.sendMessage(message);
        super.setVisibility(visibility);
    }

    //处理自动归位
    private void place() {
        if (!isDrawTriangle || (Math.abs(location[4] - TagView.this.x) < radius &&
                Math.abs(location[5] - TagView.this.y) < radius)) {
            //归位结束
            Message message = handler.obtainMessage();
            message.what = STOP;
            handler.sendMessage(message);
            return;
        }
        float x = 0;
        float y = 0;
        //新的距离
        switch ((int) location[18]) {
            case 1:
                x = TagView.this.x - Math.abs(TagView.this.x - location[4]) / 1.1f;
                y = TagView.this.y - Math.abs(TagView.this.y - location[5]) / 1.1f;
                break;
            case 2:
                x = TagView.this.x + Math.abs(TagView.this.x - location[4]) / 1.1f;
                y = TagView.this.y - Math.abs(TagView.this.y - location[5]) / 1.1f;
                break;
            case 3:
                x = TagView.this.x + Math.abs(TagView.this.x - location[4]) / 1.1f;
                y = TagView.this.y + Math.abs(TagView.this.y - location[5]) / 1.1f;
                break;
            case 4:
                x = TagView.this.x - Math.abs(TagView.this.x - location[4]) / 1.1f;
                y = TagView.this.y + Math.abs(TagView.this.y - location[5]) / 1.1f;
                break;
            default:
                x = TagView.this.x;
                y = TagView.this.y;
                break;
        }
        location = calculate(x, y, location);
        invalidate();

        Message messagePlace = handler.obtainMessage();
        messagePlace.what = PLACE;
        handler.sendMessageDelayed(messagePlace, 10);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        this.width = getMeasuredWidth();
        this.height = getMeasuredHeight();
        this.x = width / 2;
        this.y = height / 2;
        this.smallX = this.x;
        this.smallY = this.y;
        this.location = new float[]{0f, 0f, 0f, 0f, x, y, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f};
    }

    //获取文字的长度
    private int[] getWidthAndHeight(String value, int size) {
        Paint paint = new Paint();
        paint.setTextSize(size);
        Rect rect = new Rect();
        //返回包围整个字符串的最小的一个Rect区域
        paint.getTextBounds(value, 0, value.length(), rect);
        return new int[]{rect.width(), rect.height()};
    }
}
